<?php
namespace api\modules\v1\models;

use api\components\ApiModel;
use api\components\RuleUtil;
use common\models\ARCoinType;
use common\models\ARCurrencyType;
use common\models\ARNeed;
use common\models\ARUserConfig;
use common\models\ARWallet;
use Yii;
use yii\helpers\ArrayHelper;

/**
 * 广告模型
 * @author ZCY
 */
class Need extends ApiModel
{
    const SCENARIO_BUY = 'buy';
    const SCENARIO_SELL = 'sell';
    const SCENARIO_LIST = 'list';
    const SCENARIO_INFO = 'info';

    const SORTASC = 'asc';
    const SORTDESC = 'desc';

    public $need_id;
    public $country;
    public $provinces;
    public $paymode;
    public $price;
    public $coin;
    public $currency;
    public $amount_min;
    public $amount_max;
    public $trans_mode;
    public $meno;
    public $type;
    public $amount;
    public $sort_field;
    public $sort_type;
    public $page;
    public $size;

    private $_needinfo;

    /**
     * @inheritdoc
     */
    public function attributeLabels()
    {
        return [
            'need_id'    => '广告ID',
            'country'    => '国家',
            'provinces'  => '省份',
            'paymode'    => '支付方式',
            'coin'       => '币种',
            'currency'   => '法币',
            'price'      => '价格',
            'amount_min' => '最小额度',
            'amount_max' => '最大额度',
            'trans_mode' => '交易模式',
            'meno'       => '备注信息',
            'size'       => '分页大小',
            'page'       => '当前页',
            'type'       => '需求类型',
            'amount'     => '交易额度',
            'sort_field' => '排序字段',
            'sort_type'  => '排序方式',
        ];
    }

    /**
     * @inheritdoc
     */
    public function scenarios()
    {
        return [
            self::SCENARIO_BUY  => ['country', 'provinces', 'paymode', 'coin', 'currency', 'price', 'amount_min', 'amount_max', 'trans_mode', 'meno'],
            self::SCENARIO_SELL => ['country', 'provinces', 'paymode', 'coin', 'currency', 'price', 'amount_min', 'amount_max', 'trans_mode', 'meno'],
            self::SCENARIO_LIST => ['type', 'coin', 'currency', 'paymode', 'country', 'provinces', 'amount', 'sort_field', 'sort_type', 'page', 'size'],
            self::SCENARIO_INFO => ['need_id'],
        ];
    }

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['country', 'provinces', 'paymode', 'coin', 'price', 'amount_min', 'amount_max', 'trans_mode', 'meno', 'currency', 'type', 'need_id'], 'trim'],
            [['price', 'amount_min', 'amount_max', 'type', 'need_id'], 'required'],
            ['need_id', 'needCheck'],
            [['coin', 'currency'], 'required', 'on' => [self::SCENARIO_BUY, self::SCENARIO_SELL]],
            [['paymode', 'country'], 'required', 'on' => [self::SCENARIO_BUY, self::SCENARIO_SELL]],
            ['provinces', 'required', 'when' => function ($model) {
                return strtoupper($this->country) === 'CN';
            }],
            ['provinces', 'checkProvicnce'],
            ['type', 'in', 'range' => [ARNeed::TYPE_IN, ARNeed::TYPE_OUT]],
            ['trans_mode', 'default', 'value' => ARNeed::TRANS_MODE_BROKER],
            ['trans_mode', 'in', 'range' => [ARNeed::TRANS_MODE_BROKER, ARNeed::TRANS_MODE_UNBROKER]],
            ['paymode', 'in', 'range' => [ARWallet::TYPE_BANK, ARWallet::TYPE_ZFB, ARWallet::TYPE_OTHER], 'on' => [self::SCENARIO_LIST]],
            ['paymode', 'paymodeCheck', 'on' => [self::SCENARIO_BUY, self::SCENARIO_SELL]],
            ['coin', 'coinCheck'],
            ['currency', 'currencyCheck'],
            [['amount_min', 'amount_max', 'price', 'amount'], 'number'],
            [['amount_min', 'price'], 'compare', 'compareValue' => 0.0001, 'operator' => '>='],
            ['amount_max', 'compare', 'compareAttribute' => 'amount_min', 'operator' => '>='],
            ['sort_field', 'default', 'value' => 'created_at'],
            ['sort_type', 'default', 'value' => 'desc'],
            ['sort_type', 'in', 'range' => [self::SORTASC, self::SORTDESC]],
            ['country', 'checkCountry'],
            ['size', 'default', 'value' => 10],
            ['page', 'default', 'value' => 1],
            [['size', 'page'], 'integer'],

        ];
    }

    /**
     * 币种检测
     * @param $attribute
     * @param $params
     */
    public function coinCheck($attribute, $params)
    {
        $coinInfo = ARCoinType::find()->where(['status' => ARCoinType::STATUS_ACTIVE, 'id' => $this->$attribute])->one();
        if (!$coinInfo) {
            $this->addError($attribute, '币种类型不合法!');
        }
    }

    /**
     * 法币检测
     * @param $attribute
     * @param $params
     */
    public function currencyCheck($attribute, $params)
    {
        $currencyInfo = ARCurrencyType::find()->where(['status' => ARCurrencyType::STATUS_ACTIVE, 'id' => $this->$attribute])->one();
        if (!$currencyInfo) {
            $this->addError($attribute, '法币类型不合法!');
        }
    }

    /**
     * 支付方式检测
     */
    public function paymodeCheck($attribute, $params)
    {
        $walletInfo = ARWallet::find()->where(['uid' => Yii::$app->user->id, 'id' => $this->$attribute])->one();
        if (!$walletInfo) {
            $this->addError($attribute, '支付方式不合法');
        }
    }

    /**
     * 广告ID检测
     */
    public function needCheck($attribute, $params)
    {
        $needInfo = ARNeed::find()->where(['id' => $this->$attribute])->one();
        if (!$needInfo) {
            $this->addError($attribute, '广告ID不合法!');
        }
        $this->_needinfo = $needInfo;
    }

    /**
     * 国家校验
     */
    public function checkCountry($attribute, $params)
    {
        list($res, $data) = RuleUtil::checkCountry($this->$attribute);
        if (!$res) {
            $this->addError($attribute, '国家名称不合法');
        }
    }

    /**
     * 省份检测
     * @param unknown $attribute
     * @param unknown $params
     */
    public function checkProvicnce($attribute, $params)
    {
        if (strtoupper($this->country) == 'CN') {
            list($res, $data) = RuleUtil::checkProvince($this->$attribute);
            if (!$res) {
                $this->addError($attribute, '省份名称不合法');
            }
        }

    }

    /**
     * 获取挂单余额,交易中额度
     */
    public static function getNeedAmountInfo($coin)
    {
        $uid = Yii::$app->user->id;
        $info = ARNeed::find()->where(['uid' => $uid, 'coin' => $coin])
            ->select('sum(amount_trading) as amount_trading_total,sum(amount_remain) as amount_remain_total')
            ->asArray()->one();
        if ($info) {
            return $info;
        } else {
            return ['amount_remain_total' => 0, 'amount_trading_total' => 0];
        }

    }

    /**
     * 发布购买广告
     */
    public function buy()
    {
        if (!$this->validate()) {
            self::getErrorMessge($this);
        }
        $need = new ARNeed();
        $need->setScenario(ARNeed::SCENARIO_BUY);
        $need->attributes = $this->attributes;
        $need->uid = Yii::$app->user->id;
        $need->amount_trading = 0;
        $need->amount_used = 0;
        $need->type = ARNeed::TYPE_IN;
        $need->amount_remain = $this->amount_max;
        $need->expired_at = -1; //默认长期有效
        if (!$need->save()) {
            self::getErrorMessge($need);
        }
        return ['id' => $need->id];
    }

    /**
     * 发布卖出广告
     */
    public function sell()
    {
        if (!$this->validate()) {
            self::getErrorMessge($this);
        }
        $uid = Yii::$app->user->id;
        $transaction = Yii::$app->db->beginTransaction();
        try {

            $need = new ARNeed();
            $need->setScenario(ARNeed::SCENARIO_SELL);
            $need->attributes = $this->attributes;
            $need->uid = Yii::$app->user->id;
            $need->amount_trading = 0;
            $need->amount_used = 0;
            $need->type = ARNeed::TYPE_OUT;
            $need->amount_remain = $this->amount_max;
            $need->expired_at = -1; //默认长期有效
            if (!$need->save()) {
                self::getErrorMessge($need);
            }
            $scale = Yii::$app->params['scale'];
            $fee = bcmul(sprintf("%.{$scale}f", $this->amount_max), bcadd(sprintf("%.{$scale}f", Yii::$app->params['server_charge']['broker']), sprintf("%.{$scale}f", Yii::$app->params['server_charge']['platform']), $scale), $scale);
            Assets::beSelling($need->id, $uid, $this->coin, $this->amount_max, $fee);
            $transaction->commit();
            return ['id' => $need->id];
        } catch (\Exception $e) {
            $transaction->rollBack();
            throw $e;
        }
    }

    /**
     * 需求列表
     */
    public function needlist()
    {
        if (!$this->validate()) {
            self::getErrorMessge($this);
        }
        $model = ARNeed::find();
        if ($this->coin) {
            $model->andWhere([ARNeed::tableName() . '.coin' => $this->coin]);
        }
        if ($this->currency) {
            $model->andWhere([ARNeed::tableName() . '.currency' => $this->currency]);
        }
        if ($this->type) {
            $model->andWhere([ARNeed::tableName() . '.type' => $this->type]);
        }
        $model->andWhere(['>', ARNeed::tableName() . '.amount_remain', 0]);
        $model->joinWith(['user', 'scoring', 'coinType', 'currencyType', 'wallet' => function ($query) {
            if ($this->paymode) {
                $query->andWhere([ARWallet::tableName() . '.type' => $this->paymode]);
            }
        },
        ]);
        if ($this->sort_type == self::SORTASC) {
            $sorttype = SORT_ASC;
        } else {
            $sorttype = SORT_DESC;
        }

        $count = $model->count();

        $data = $model->limit($this->size)->offset($this->size * ($this->page - 1))->orderBy([$this->sort_field => $sorttype])->all();
        $rows = ArrayHelper::toArray($data, [
            ARNeed::className() => [
                'id',
                'type',
                'uid',
                'nickname'  => function ($row) {
                    return $row->user->nickname;
                },
                'order_num' => function ($row) {
                    //交易笔数
                    return $row->scoring ? $row->scoring->transaction_num : 0;
                },
                'rating'    => function ($row) {
                    return $row->scoring ? $row->scoring->rating . '%' : '0%';
                },
                'pay_mode'  => function ($row) {
                    return $row->wallet ? $row->wallet->other_type : '未知类型';
                },
                'price',
                'coin'      => function ($row) {
                    return $row->coinType->name;
                },
                'currency'  => function ($row) {
                    return $row->currencyType->name;
                },
                'amount_min',
                'amount_max',
            ],
        ]);
        return ['count' => $count, 'rows' => $rows];
    }

    /**
     * 广告详情
     */
    public function needinfo()
    {
        if (!$this->validate()) {
            self::getErrorMessge($this);
        }
        $needinfo = ArrayHelper::toArray($this->_needinfo, [
            ARNeed::className() => [
                'id',
                'uid',
                'nickname'  => function ($row) {
                    return $row->user->nickname;
                },
                'pay_mode'  => function ($row) {
                    return $row->wallet ? $row->wallet->other_type : '未知类型';
                },
                'price',
                'coin'      => function ($row) {
                    return $row->coinType->name;
                },
                'currency'  => function ($row) {
                    return $row->currencyType->name;
                },
                'amount_min',
                'amount_max',
                'country'  => function ($row) {
                    list($flag,$data)= RuleUtil::checkCountry($row->country);
                    return $data['ch_name'];
                },
                'provinces' => function ($row) {
                    list($flag,$data)= RuleUtil::checkProvince($row->provinces);
                    return $data['p_name'];
                },
                'order_num' => function ($row) {
                    //交易笔数
                    return $row->scoring ? $row->scoring->transaction_num : 0;
                },
                'rating'    => function ($row) {
                    return $row->scoring ? $row->scoring->rating . '%' : '0%';
                },
                'amount_remain',
                'is_real'   => function ($row) {
                    return ARUserConfig::find()->where(['uid' => $row->uid])->one()->is_real;
                },
                'meno',
                'trans_mode',
            ],
        ]);
        return ['need_info' => $needinfo];
    }

    /**
     * 拒绝订单时返还需求数量
     */
    public static function returnNeed($need_id, $amount)
    {
        $need = ARNeed::findOne($need_id);
        $need->setScenario(ARNeed::SCENARIO_SELL);
        $need->amount_trading = $need->amount_trading - $amount;
        $need->amount_remain = $need->amount_remain + $amount;
        if(!$need->update()){
            self::getErrorMessge($need);
        }
    }
}
